import 'dart:async';
import 'package:flutter/foundation.dart';
import 'hive_storage.dart';
import 'shared_prefs_storage.dart';
import '../exceptions/app_exceptions.dart';
import '../utils/logger.dart';

enum StorageType { sharedPrefs, hive }

class StorageService {
  static StorageService? _instance;
  static StorageService get instance => _instance ??= StorageService._internal();
  
  late HiveStorage _hiveStorage;
  late SharedPrefsStorage _sharedPrefsStorage;
  
  StorageService._internal() {
    _hiveStorage = HiveStorage.instance;
    _sharedPrefsStorage = SharedPrefsStorage.instance;
  }

  // 初始化存储服务
  Future<void> init() async {
    try {
      if (kIsWeb) {
        // Web平台只初始化SharedPreferences
        await _sharedPrefsStorage.init();
        AppLogger.info('Storage service initialized for web');
      } else {
        // 移动端初始化所有存储
        await Future.wait([
          _hiveStorage.init(),
          _sharedPrefsStorage.init(),
        ]);
        AppLogger.info('Storage service initialized');
      }
    } catch (e) {
      AppLogger.error('Failed to initialize storage service', e);
      if (kIsWeb) {
        // Web平台初始化失败时使用内存存储
        AppLogger.info('Fallback to memory storage for web');
      } else {
        rethrow;
      }
    }
  }

  // 用户偏好设置存储
  Future<void> setUserPreference(String key, dynamic value) async {
    try {
      if (value is String) {
        await _sharedPrefsStorage.setString(key, value);
      } else if (value is int) {
        await _sharedPrefsStorage.setInt(key, value);
      } else if (value is double) {
        await _sharedPrefsStorage.setDouble(key, value);
      } else if (value is bool) {
        await _sharedPrefsStorage.setBool(key, value);
      } else if (value is List<String>) {
        await _sharedPrefsStorage.setStringList(key, value);
      } else if (value is Map<String, dynamic>) {
        await _sharedPrefsStorage.setObject(key, value);
      } else if (value is List<Map<String, dynamic>>) {
        await _sharedPrefsStorage.setObjectList(key, value);
      } else {
        throw StorageException(
          message: 'Unsupported value type: ${value.runtimeType}',
        );
      }
      AppLogger.debug('Set user preference: $key = $value');
    } catch (e) {
      AppLogger.error('Failed to set user preference: $key', e);
      rethrow;
    }
  }

  // 获取用户偏好设置
  T? getUserPreference<T>(String key, [T? defaultValue]) {
    try {
      dynamic value;
      if (T == String) {
        value = _sharedPrefsStorage.getString(key, defaultValue as String?);
      } else if (T == int) {
        value = _sharedPrefsStorage.getInt(key, defaultValue as int?);
      } else if (T == double) {
        value = _sharedPrefsStorage.getDouble(key, defaultValue as double?);
      } else if (T == bool) {
        value = _sharedPrefsStorage.getBool(key, defaultValue as bool?);
      } else if (T == List<String>) {
        value = _sharedPrefsStorage.getStringList(key, defaultValue as List<String>?);
      } else if (T == Map<String, dynamic>) {
        value = _sharedPrefsStorage.getObject(key, defaultValue as Map<String, dynamic>?);
      } else if (T == List<Map<String, dynamic>>) {
        value = _sharedPrefsStorage.getObjectList(key, defaultValue as List<Map<String, dynamic>>?);
      } else {
        value = defaultValue;
      }
      AppLogger.debug('Get user preference: $key = $value');
      return value as T?;
    } catch (e) {
      AppLogger.error('Failed to get user preference: $key', e);
      return defaultValue;
    }
  }

  // 删除用户偏好设置
  Future<void> removeUserPreference(String key) async {
    try {
      await _sharedPrefsStorage.remove(key);
      AppLogger.debug('Remove user preference: $key');
    } catch (e) {
      AppLogger.error('Failed to remove user preference: $key', e);
      rethrow;
    }
  }

  // 清除所有用户偏好设置
  Future<void> clearUserPreferences() async {
    try {
      await _sharedPrefsStorage.clear();
      AppLogger.debug('Clear all user preferences');
    } catch (e) {
      AppLogger.error('Failed to clear user preferences', e);
      rethrow;
    }
  }

  // 数据存储 (使用Hive)
  Future<void> setData<T>(String boxName, dynamic key, T value) async {
    try {
      await _hiveStorage.put(boxName, key, value);
      AppLogger.debug('Set data: $boxName[$key] = $value');
    } catch (e) {
      AppLogger.error('Failed to set data: $boxName[$key]', e);
      rethrow;
    }
  }

  // 获取数据
  Future<T?> getData<T>(String boxName, dynamic key, [T? defaultValue]) async {
    try {
      final value = await _hiveStorage.get<T>(boxName, key, defaultValue);
      AppLogger.debug('Get data: $boxName[$key] = $value');
      return value;
    } catch (e) {
      AppLogger.error('Failed to get data: $boxName[$key]', e);
      return defaultValue;
    }
  }

  // 删除数据
  Future<void> removeData(String boxName, dynamic key) async {
    try {
      await _hiveStorage.delete(boxName, key);
      AppLogger.debug('Remove data: $boxName[$key]');
    } catch (e) {
      AppLogger.error('Failed to remove data: $boxName[$key]', e);
      rethrow;
    }
  }

  // 清空数据box
  Future<void> clearDataBox(String boxName) async {
    try {
      await _hiveStorage.clear(boxName);
      AppLogger.debug('Clear data box: $boxName');
    } catch (e) {
      AppLogger.error('Failed to clear data box: $boxName', e);
      rethrow;
    }
  }

  // 批量设置数据
  Future<void> setDataBatch<T>(String boxName, Map<dynamic, T> entries) async {
    try {
      await _hiveStorage.putAll(boxName, entries);
      AppLogger.debug('Set data batch: $boxName = ${entries.keys}');
    } catch (e) {
      AppLogger.error('Failed to set data batch: $boxName', e);
      rethrow;
    }
  }

  // 获取数据列表
  Future<List<T>> getDataList<T>(String boxName) async {
    try {
      final values = await _hiveStorage.getValues<T>(boxName);
      final list = values.toList();
      AppLogger.debug('Get data list: $boxName = ${list.length} items');
      return list;
    } catch (e) {
      AppLogger.error('Failed to get data list: $boxName', e);
      return [];
    }
  }

  // 检查数据是否存在
  Future<bool> containsData(String boxName, dynamic key) async {
    try {
      final result = await _hiveStorage.containsKey(boxName, key);
      AppLogger.debug('Contains data: $boxName[$key] = $result');
      return result;
    } catch (e) {
      AppLogger.error('Failed to check data: $boxName[$key]', e);
      return false;
    }
  }

  // 获取数据大小
  Future<int> getDataSize(String boxName) async {
    try {
      final size = await _hiveStorage.getLength(boxName);
      AppLogger.debug('Get data size: $boxName = $size');
      return size;
    } catch (e) {
      AppLogger.error('Failed to get data size: $boxName', e);
      return 0;
    }
  }

  // 监听数据变化
  Stream<T?> watchData<T>(String boxName, dynamic key) async* {
    try {
      await for (final event in _hiveStorage.watch(boxName, key: key)) {
        if (event.deleted) {
          yield null;
        } else {
          yield event.value as T?;
        }
      }
    } catch (e) {
      AppLogger.error('Failed to watch data: $boxName[$key]', e);
      rethrow;
    }
  }

  // 缓存管理
  Future<void> setCacheData<T>(String key, T value, {Duration? expiry}) async {
    try {
      final cacheData = {
        'value': value,
        'timestamp': DateTime.now().millisecondsSinceEpoch,
        'expiry': expiry?.inMilliseconds,
      };
      await _hiveStorage.put('cache', key, cacheData);
      AppLogger.debug('Set cache data: $key = $value');
    } catch (e) {
      AppLogger.error('Failed to set cache data: $key', e);
      rethrow;
    }
  }

  // 获取缓存数据
  Future<T?> getCacheData<T>(String key) async {
    try {
      final cacheData = await _hiveStorage.get<Map<String, dynamic>>('cache', key);
      if (cacheData == null) {
        return null;
      }

      final timestamp = cacheData['timestamp'] as int;
      final expiry = cacheData['expiry'] as int?;
      
      if (expiry != null) {
        final now = DateTime.now().millisecondsSinceEpoch;
        if (now - timestamp > expiry) {
          // 缓存已过期，删除并返回null
          await _hiveStorage.delete('cache', key);
          AppLogger.debug('Cache expired: $key');
          return null;
        }
      }

      final value = cacheData['value'] as T;
      AppLogger.debug('Get cache data: $key = $value');
      return value;
    } catch (e) {
      AppLogger.error('Failed to get cache data: $key', e);
      return null;
    }
  }

  // 删除缓存数据
  Future<void> removeCacheData(String key) async {
    try {
      await _hiveStorage.delete('cache', key);
      AppLogger.debug('Remove cache data: $key');
    } catch (e) {
      AppLogger.error('Failed to remove cache data: $key', e);
      rethrow;
    }
  }

  // 清除所有缓存
  Future<void> clearCache() async {
    try {
      await _hiveStorage.clear('cache');
      AppLogger.debug('Clear all cache');
    } catch (e) {
      AppLogger.error('Failed to clear cache', e);
      rethrow;
    }
  }

  // 清除过期缓存
  Future<void> clearExpiredCache() async {
    try {
      final keys = await _hiveStorage.getKeys('cache');
      final now = DateTime.now().millisecondsSinceEpoch;
      final expiredKeys = <dynamic>[];

      for (final key in keys) {
        final cacheData = await _hiveStorage.get<Map<String, dynamic>>('cache', key);
        if (cacheData != null) {
          final timestamp = cacheData['timestamp'] as int;
          final expiry = cacheData['expiry'] as int?;
          
          if (expiry != null && now - timestamp > expiry) {
            expiredKeys.add(key);
          }
        }
      }

      if (expiredKeys.isNotEmpty) {
        await _hiveStorage.deleteAll('cache', expiredKeys);
        AppLogger.debug('Cleared expired cache: ${expiredKeys.length} items');
      }
    } catch (e) {
      AppLogger.error('Failed to clear expired cache', e);
      rethrow;
    }
  }

  // 获取存储信息
  Future<Map<String, dynamic>> getStorageInfo() async {
    try {
      final sharedPrefsSize = _sharedPrefsStorage.getSize();
      final cacheSize = await _hiveStorage.getLength('cache');
      
      final info = {
        'sharedPrefsSize': sharedPrefsSize,
        'cacheSize': cacheSize,
        'totalSize': sharedPrefsSize + cacheSize,
      };
      
      AppLogger.debug('Get storage info: $info');
      return info;
    } catch (e) {
      AppLogger.error('Failed to get storage info', e);
      return {};
    }
  }

  // 关闭存储服务
  Future<void> close() async {
    try {
      await _hiveStorage.closeAllBoxes();
      AppLogger.info('Storage service closed');
    } catch (e) {
      AppLogger.error('Failed to close storage service', e);
      rethrow;
    }
  }
}